package research.persistence;

import java.util.HashSet;
import java.util.Set;

import research.dao.hibernate.HibernatePersistance;
import research.entity.Entity;

public final class PersistenceManager implements IPersistenceManager {
	private static PersistenceManager INSTANCE = null;
	private Set<IPersistenceListener> listeners = null;
	private IPersistenceDataSource source = null;
	private IPersistenceListener feedback = null;

	public PersistenceManager(IPersistenceDataSource source, IPersistenceListener feedback) {
		super();
		this.source = source;
		this.feedback = feedback;
		this.listeners = new HashSet<IPersistenceListener>();
	}
	
	private static PersistenceManager createNewInstance() {
		HibernatePersistance per = new HibernatePersistance();
		PersistenceManager manager = new PersistenceManager(per, per);
		return manager;
	}

	public static PersistenceManager getInstance() {
		if (INSTANCE == null)
			INSTANCE = createNewInstance();
			
		return INSTANCE;
	}
	
	@Override
	public void addListener(IPersistenceListener lisetner){
		if (listeners.contains(lisetner))
			throw new PersistenceException("Duplicate persistence listener attachment");
		listeners.add(lisetner);
	}
	
	@Override
	public void removeListener(IPersistenceListener listener){
		if (!listeners.contains(listener))
			throw new PersistenceException("Removing of not attached listener");
		listeners.remove(listener);
	}
	
	@Override
	public void add(Entity entity) {
		feedback.add(entity);
		for (IPersistenceListener listener : listeners)
			listener.add(entity);
	}
	
	@Override
	public void remove(Entity entity) {
		for (IPersistenceListener listener : listeners)
			listener.remove(entity);
		
		feedback.remove(entity);
	}
	
	@Override
	public void update(Entity entity) {
		feedback.update(entity);
		for (IPersistenceListener listener : listeners)
			listener.update(entity);
	}
	
	@Override
	public IPersistenceDataSource getDataSource() {
		return source;
	}

	@Override
	public void persist(Entity entity) {
		if (getDataSource().isPersistent(entity)) {
			update(entity);
		} else {
			add(entity);
		}
	}
}
